import Context from "./Context";
import Common from "./utils/Common";
import Handler from "./handler/Handler";
import MessageDelegate from "./handler/MessageDelegate";

export default abstract class Component extends cc.Component implements Handler {
    // 窗口代理消息对象.
    private readonly _handler: Handler = null;

    protected constructor() {
        super();
        this._handler = new MessageDelegate(this);
    }

    public handleMessage(message: string, args: any[]): boolean {
        return false;
    }

    public onShow() {

    }

    public onHide() {

    }

    // 返回需要监听的消息.
    protected listen(): string[] {
        return [];
    }

    // 中转一层,防止同一组件的事件监听target 被意外设置成其他对象.
    protected setClickListener(node: cc.Node | cc.Component, clickListener: (ev: cc.Event) => void) {
        Common.setClickListenerAnim(node, true, clickListener, this);
    }

    protected setClickListenerAnim(node: cc.Node | cc.Component, anim: boolean, clickListener: (ev: cc.Event) => void) {
        Common.setClickListenerAnim(node, anim, clickListener, this);
    }

    protected setDragListener(node: cc.Node | cc.Component, dragListener: (p: cc.Vec2, pDelta: cc.Vec2, pDistance: cc.Vec2) => void) {
        Common.setDragListener(node, dragListener, this);
    }

    protected setLongClickListener(node: cc.Node | cc.Component, longClickListener: (ev: cc.Event) => void) {
        Common.setLongClickListener(node, longClickListener, this);
    }

    protected setPressedListener(node: cc.Node | cc.Component, pressedListener: (nd: cc.Node, p: cc.Vec2) => void) {
        Common.setPressedListener(node, pressedListener, this);
    }

    protected setOnReleaseListner(node: cc.Node | cc.Component, releaseListener: (nd: cc.Node, p: cc.Vec2) => void) {
        Common.setOnReleaseListener(node, releaseListener, this);
    }

    protected setLongPressedListener(node: cc.Node | cc.Component, longPressedListener: (nd: cc.Node, p: cc.Vec2) => void) {
        Common.setLongPressedListener(node, longPressedListener, this);
    }

    protected performClick(node: cc.Node | cc.Component) {
        Common.performClick(node);
    }

    protected performLongClick(node: cc.Node | cc.Component) {
        Common.performLongClick(node);
    }

    protected performPressed(node: cc.Node | cc.Component) {
        Common.performPressed(node);
    }

    protected performLongPressed(node: cc.Node | cc.Component) {
        Common.performLongPressed(node);
    }

    protected setBubble(node: cc.Node | cc.Component, bubble: boolean) {
        Common.setBubble(node, bubble);
    }

    // 从事件中获取点击目标的组件.
    protected getFromEvent<T extends cc.Component>(ev: cc.Event, c: { prototype: T }): T {
        if (ev.target instanceof cc.Node) {
            return ev.target.getComponent(c);
        } else {
            return null;
        }
    }

    // 点击点击事件移除绑定.
    protected removeClickListener(node: cc.Node | cc.Component) {
        Common.removeClickListener(node);
    }

    protected removeLongClickListener(node: cc.Node | cc.Component) {
        Common.removeLongClickListener(node);
    }

    protected removeDragListener(node: cc.Node | cc.Component) {
        Common.removeDragListener(node);
    }

    // 发送消息.这里传递可变参数有要注意可变参数每包一层就会导致参数数组多一层.
    protected sendMessage(msg: string, args: any[] = []) {
        Context.get().messenger.sendMessage(msg, args);
    }

    // 碰撞检测函数.
    protected onBeginContact(contact: cc.PhysicsContact, self: cc.Collider, other: cc.Collider) {
        //  cc.log("发生碰撞.")
    }

    // 碰撞检测函数.
    protected onEndContact(contact: cc.PhysicsContact, self: cc.Collider, other: cc.Collider) {
        //     cc.log("碰撞结束")
    }


    protected onCollisionEnter(other: cc.Collider, self: cc.Collider) {
    }

    protected onCollisionStay(other: cc.Collider, self: cc.Collider) {
    }

    protected onCollisionExit(other: cc.Collider, self: cc.Collider) {
    }

    private onEnable() {
        const msgs = this.listen();
        if (msgs && msgs.length > 0) {
            Context.get().messenger.register(this._handler, msgs);
        }
        this.onShow();
    }

    private onDisable() {
        Context.get().messenger.unregister(this._handler, this.listen());
        this.onHide();
    }
}
